home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / wasm223.zip / MACRO.DOC < prev    next >
Text File  |  1993-05-04  |  19KB  |  470 lines

  1.  
  2.  
  3.                                  MACRO REFERENCE
  4.                                  ---------------
  5.  
  6.      Macros exist as standard text files that are compiled and run by an
  7.      application.  The library files MACRO1.ASM and MACRO2.ASM provide all
  8.      the code necessary for adding a macro language to an application.  The
  9.      routine MacAll allocates the memory required for compiling and running
  10.      macros.  MacCom compiles macro source files to an executable program
  11.      stored in memory.  MacRun executes a compiled macro.
  12.  
  13.      The default keywords of the macro language do not perform any
  14.      meaningful tasks.  A table of application specific keywords must be
  15.      created by the user before the macro language can be useful.
  16.  
  17.                               LANGUAGE DESCRIPTION
  18.                               --------------------
  19.  
  20.      The macro language is stack based and resembles the Forth programming
  21.      language.  The macro source code consists of a sequence of tokens
  22.      separated by spaces and line boundaries.  For example:
  23.  
  24.        22 11 +
  25.        33 =
  26.  
  27.      The tokens in this case are "22", "11", "+", "33", and "=".  The
  28.      location of the line break is unimportant.  These tokens could all be
  29.      placed on a single line with the same effect:
  30.  
  31.        22 11 + 33 =
  32.  
  33.      Each token performs some specific stack operation.  Numbers are pushed
  34.      on the stack, so after the first two tokens are "executed," the
  35.      numbers 22 and 11 are pushed on the stack.  A plus (+) adds the top
  36.      two numbers of the stack together, so after the plus is executed, the
  37.      22 and 11 on the stack have been replaced by a 33.  The fourth token
  38.      results in 33 being pushed on the stack (on top of the 33 remaining
  39.      after adding the 22 and 11).  Finally, the equal sign compares the top
  40.      two stack numbers, replacing them with -1 (FFFF hex) if they are equal
  41.      or 0 if they are not.  The net effect of this expression is to add 22
  42.      and 11 and compare the result to 33.  The result of the comparison, -1
  43.      in this case, is left of the stack.
  44.  
  45.      Numbers are 16 bit signed integers.  If no sign is provided, '+' is
  46.      assumed.  Hexadecimal numbers are specified by a preceding dollar sign
  47.      ($).  Characters in single quotes are translated to their ASCII value.
  48.      Some example numbers are:
  49.  
  50.        1 -3 +12414 $ABCD 'a'
  51.  
  52.      Symbols identify locations in the macro program.  Symbols are used in
  53.      branching structures and accessing data.  Symbols are defined using
  54.      the colon (:) token:
  55.  
  56.        : a_symbol
  57.  
  58.      In this case, "a_symbol" is the defined symbol because it is the token
  59.      after the colon.  Note that symbols and keywords are case-sensitive.
  60.      Creating a symbol produces no machine code.  Using a symbol pushes its
  61.  
  62.  
  63.      address on the stack:
  64.  
  65.        a_symbol JUMP
  66.  
  67.      In this case, the address of "a_symbol" is pushed on the stack and the
  68.      JUMP keyword branches to this address.  Symbols may be used before
  69.      they are defined (i.e., the macro compiler handles forward references
  70.      properly).
  71.  
  72.      Data can be declared in two ways, strings and arrays.  Strings are
  73.      created with the double quote (") token:
  74.  
  75.        " this is a string"
  76.  
  77.      The start of the string begins after the first delimiter after the
  78.      double quote and ends with a double quote.  In this case, the letter
  79.      't' is the first character of the string and the letter 'g' is the
  80.      last character of the string.  A NUL character (ASCII code 0) is
  81.      appended to the end of all strings.  Strings can contain two types of
  82.      special characters, the carat (^) and the backslash (\).  The carat
  83.      specifies a control character, for example:
  84.  
  85.         " this is a string^M^J"
  86.  
  87.      This string has a carriage return and linefeed are appended to the end
  88.      of it.  The other special character, a backslash, masks special
  89.      characters so they can be imbedded in a string, for instance:
  90.  
  91.         " this is a string \^ \" \\ "
  92.           |                |  |  |  |
  93.           |                |  |  |  end of string
  94.           |                |  |  imbed backslash
  95.           |                |  imbed double quote
  96.           |                imbed carat
  97.           start of string
  98.  
  99.      Arrays or variables (single element arrays) are created using the left
  100.      and right curved bracket ({}) tokens.  All tokens within the curved
  101.      brackets are stored as sequential 16 bit values.  The address of a
  102.      symbol may be stored by placing the symbol between the brackets.  An
  103.      example array:
  104.  
  105.        { 0 1 -6 'a' $ABCD a_symbol }
  106.  
  107.      Both strings and arrays are stored as inline data and must NOT be
  108.      executed.  Strings and arrays should be placed at the end of a macro
  109.      after the QUIT or branched around.  Strings and arrays are usually
  110.      referred to with symbols defined at the start of the data:
  111.  
  112.         : a_variable { 55 }
  113.         : an_array { 0 1 2 3 4 }
  114.  
  115.      Numbers can be stored at an address with the exclamation point (!)
  116.      token or retrieved with the '@' token:
  117.  
  118.         0 a_variable !  // store zero to a_variable
  119.  
  120.         a_variable @    // load the value stored at a_variable
  121.  
  122.  
  123.      There are four special keywords for branching.  JUMP unconditionally
  124.      branches to a location stored on the stack.  The location on the stack
  125.      usually comes from a symbol.  ?JUMP uses a location and a number on
  126.      the stack to jump only if the number is non-zero, for instance:
  127.  
  128.        22 11 + 33 =      // add numbers and compare to 33, flag on stack
  129.        a_symbol ?JUMP    // push address on stack, jump if flag non-zero
  130.  
  131.      This last sequence of tokens jumps to "a_symbol" if the result of
  132.      adding 22 and 11 is equal to 33.
  133.  
  134.      The keywords CALL and ?CALL are similar to JUMP and ?JUMP except the
  135.      current location is saved before branching.  The return token, a
  136.      semicolon (;), returns from a CALL or ?CALL.  A routine to add 22 and
  137.      11 then compare the result to 33 could be written as:
  138.  
  139.        : add_routine 22 11 + 33 = ;
  140.  
  141.      this routine is called as follows:
  142.  
  143.        add_routine CALL
  144.  
  145.      Comments can be included with the double slash (//) token.  All
  146.      characters after a double slash token are ignored until the end of the
  147.      line is reached:
  148.  
  149.        // push three numbers
  150.        1 2  // push one and two
  151.        3    // now push three
  152.  
  153.      Numbers and addresses are pushed and popped from the stack without any
  154.      type checking.  Keywords that expect an address on the stack (like
  155.      JUMP and CALL) have no way of knowing if the value it's using is valid
  156.      address or not.  An easy way to crash a macro is running something
  157.      like:
  158.  
  159.        1234 JUMP     // this will almost certainly crash
  160.  
  161.      Elements of an array can be accessed by incrementing the array address
  162.      by two for each element to skip:
  163.  
  164.        an_array 4 + @                // load the third array element: 9
  165.  
  166.        : an_array { 7 8 9 }
  167.  
  168.      Array elements must be incremented by two because each element, being
  169.      16 bit values, takes up two bytes.
  170.  
  171.      Accessing elements of a string are more complicated.  The dereference
  172.      token '@' loads two bytes, which represents two characters of a
  173.      string.  For this reason, the high byte of a dereferenced string
  174.      element must be zeroed:
  175.  
  176.        a_string 8 + @                // load the ninth and tenth elements
  177.        $FF AND                       // this zeros high byte; return 'a'
  178.  
  179.        : a_string " this is a string"
  180.  
  181.  
  182.  
  183.      A macro may be run by MacRun once it has been successfully compiled
  184.      and loaded by MacCom.  Macros begin executing from the start of the
  185.      compiled code.  Macros will terminate and return from MacRun whenever
  186.      a QUIT or BREAK is encountered.  If the execution stops because of a
  187.      BREAK, the state of the macro is preserved and the next call to MacRun
  188.      continues execution after the BREAK.  A QUIT implies the final
  189.      termination and MacRes must be called before restarting the macro.
  190.  
  191.      From a compiler standpoint, the macro language is easy to process. The
  192.      assembly equivalent of the macro expression:
  193.  
  194.        22 11 + 33 =
  195.  
  196.      is something like:
  197.  
  198.         mov ax, 22   ; 22 token, push the number
  199.         push ax      ;
  200.  
  201.         mov ax, 11   ; 11 token, push the number
  202.         push ax      ;
  203.  
  204.         pop ax       ; addition (+) token, add top two numbers
  205.         pop bx       ;
  206.         add ax, bx   ;
  207.         push ax      ;
  208.  
  209.         mov ax, 33   ; 33 token, push the number
  210.         push ax      ;
  211.  
  212.         pop ax       ; compare (=) token, compare top two numbers
  213.         pop dx       ;
  214.         sub bx, bx   ;
  215.         cmp ax, dx   ;
  216.         jne xyz      ;
  217.         dec bx       ;
  218.        xyz push bx   ;
  219.  
  220.                                 LANGUAGE KEYWORDS
  221.                                 -----------------
  222.  
  223.      This section lists all the built-in keywords to the macro language.
  224.      Many of the keywords are identical to Forth keywords (or "words" as
  225.      they're called in Forth).  Other keywords look like Forth but behave
  226.      differently.
  227.  
  228.      There are two distinct types of arguments for the keywords.  The first
  229.      is arguments that are taken from the source file during compilation.
  230.      The keywords that use this type of arguments are :, ", {, //, ALLOC,
  231.      and INCLUDE.  All the other keywords use the stack for their arguments
  232.      during execution.  The syntax for stack arguments is something like:
  233.  
  234.        n1 n2 n3 - n4 n5
  235.  
  236.      In this case, the keyword expects three stack arguments and returns
  237.      two stack arguments.  n1, n2, and n3 are the top three stack items
  238.      before the keyword has executed.  n4 and n5 are the stack items
  239.      remaining when the keyword is finished.  Some keywords expect no
  240.      arguments or return no arguments, in which case the left or right side
  241.  
  242.  
  243.      of the dash (-) will be blank.  Entry arguments (left side of dash)
  244.      and exit arguments (right side of dash) are listed left to right as
  245.      they would be pushed on the stack, so the leftmost argument is always
  246.      the top stack element.  For instance, the syntax for ROT is:
  247.  
  248.        n1 n2 n3 - n2 n3 n1
  249.  
  250.      After a ROT (rotate), the original third item down becomes the new top
  251.      item, the original top item becomes the new second item, and the
  252.      original second item becomes the new third item:
  253.  
  254.        3 4 5 ROT     // after this the stack is 4 5 3, 3 is new top element
  255.  
  256.      The syntax for divide (/) is:
  257.  
  258.        n1 n2 - n3
  259.  
  260.      where n3 = n1 / n2, so:
  261.  
  262.        10 5 /        // this divides 10 by 5, leaving 2 on the stack
  263.  
  264.      Some keywords return different sets of arguments depending on the
  265.      entry arguments.  In this case the alternate argument sets are
  266.      separated by a vertical bar (|).
  267.  
  268.      Define/Declare
  269.      --------------
  270.  
  271.        :        symbol               define a symbol
  272.  
  273.        "        ccccc"               declare string data
  274.        {        n1, n2, ... }        declare array data
  275.        ALLOC    n                    declare n bytes of data (zeros)
  276.  
  277.        !        n a -                store n to address a
  278.        @        a - n                load n from address a
  279.  
  280.      Constants
  281.      ---------
  282.  
  283.        FALSE    - 0                  load false (0)
  284.        TRUE     - -1                 load true (NOT 0)
  285.        HERE     - n                  load current address
  286.  
  287.      Arithmetic
  288.      ----------
  289.  
  290.        +        n1 n2 - n3           addition, n3 = n1 + n2
  291.        -        n1 n2 - n3           subtraction, n3 = n1 - n2
  292.        *        n1 n2 - n3           multiplication, n3 = n1 * n2
  293.        /        n1 n2 - n3           division, n3 = n1 / n2
  294.  
  295.        1+       n1 - n2              increment, n2 = n1 + 1
  296.        1-       n1 - n2              decrement, n2 = n1 - 1
  297.        2+       n1 - n2              add two, n2 = n1 + 2
  298.        2-       n1 - n2              subtract two, n2 = n1 - 2
  299.        2*       n1 - n2              multiply times two, n2 = n1 * 2
  300.        2/       n1 - n2              divide by two, n2 = n1 / 2
  301.  
  302.  
  303.        MOD      n1 n2 - n3           remainder, n3 = n1 MOD n2
  304.        /MOD     n1 n2 - n3 n4        divide and remainder, n3 = n1 MOD n2
  305.                                                            n4 = n1 / n2
  306.  
  307.        MIN      n1 n2 - n3           minimum, n3 is minimum of n1 and n2
  308.        MAX      n1 n2 - n3           maximum, n3 is maximum of n1 and n2
  309.        NEGATE   n1 - n2              negative, n2 = -n1
  310.        ABS      n1 - n2              absolute value, n2 is abs of n1
  311.  
  312.      Stack
  313.      -----
  314.  
  315.        DUP      n - n n              duplicate top item
  316.        ?DUP     n - n | n n          duplicate top item if non-zero
  317.        DROP     n -                  remove top item
  318.        SWAP     n1 n2 - n2 n1        swap top two items
  319.        OVER     n1 n2 - n1 n2 n1     copy second item to top
  320.        PICK     ... i - n            copy i-th item to top
  321.        ROT      n1 n2 n3 - n2 n3 n1  roll third item to top
  322.  
  323.      Conditional
  324.      -----------
  325.  
  326.        =        n1 n2 - 0 | -1       return -1 if items equal, 0 if not
  327.        >        n1 n2 - 0 | -1       return -1 if n1 > n2, 0 if not
  328.        <        n1 n2 - 0 | -1       return -1 if n1 < n2, 0 if not
  329.  
  330.        0=       n - 0 | -1           return -1 if n = 0, 0 if not
  331.        0>       n - 0 | -1           return -1 if n > 0, 0 if not
  332.        0<       n - 0 | -1           return -1 if n < 0, 0 if not
  333.  
  334.        AND      n1 n2 - n3           logical AND, n3 = n1 AND n2
  335.        NOT      n1 - n2              logical NOT, n2 = NOT n1
  336.        OR       n1 n2 - n3           logical OR, n3 = n1 OR n2
  337.  
  338.      Branching
  339.      ---------
  340.  
  341.        ;                             return from CALL or ?CALL
  342.        CALL     a -                  call a
  343.        ?CALL    f a -                call a if f
  344.        JUMP     a -                  jump to a
  345.        ?JUMP    f a -                jump to a if f
  346.  
  347.      Other
  348.      -----
  349.  
  350.        //                            comment
  351.        BREAK                         break into macro
  352.        INCLUDE  f                    include macro file f
  353.        QUIT                          terminate macro
  354.  
  355.                                LANGUAGE EXTENSIONS
  356.                                -------------------
  357.  
  358.      Application specific keywords must be defined before macros can do
  359.      anything useful.  The symbol MacUsr must exist to define a table
  360.      containing a list of keyword entries.  Each keyword entry consists of
  361.  
  362.  
  363.      an ASCIIZ string (the keyword) followed by the offset of the procedure
  364.      to service that keyword.  The list of entries is terminated by a null
  365.      string.
  366.  
  367.      The procedure to service a keyword should be FAR.  Upon entry, all the
  368.      segment registers are pointing to CS (as usual).  All the other
  369.      registers are undefined.  The registers SI, DI, BP, DS, and ES should
  370.      be preserved.  Arguments are stored and retrieved from the macro stack
  371.      with the MacSto and MacLoa routines.  Retrieved addresses are 16 bit
  372.      offsets into the macro code/data segment.  MacLoa returns the macro
  373.      code/data segment in DX so you can directly access macro data by
  374.      loading DX into a segment register.
  375.  
  376.      The following is a simple example that adds two keywords to the macro
  377.      language and then runs a macro called TEST.MAC:
  378.  
  379.        ; This program compiles and runs a macro file call TEST.MAC
  380.        ; IMPORTANT: compile and allocation errors are not detected.  If
  381.        ; there is an error, this program will crash.
  382.  
  383.                ; these are the library files needed
  384.  
  385.                INCLUDE 'file.asm'
  386.                INCLUDE 'buffer1.asm'
  387.                INCLUDE 'buffer2.asm'
  388.                INCLUDE 'buffer4.asm'
  389.  
  390.                INCLUDE 'case1.asm'
  391.                INCLUDE 'convert.asm'
  392.  
  393.                INCLUDE 'memory.asm'
  394.                INCLUDE 'stack.asm'
  395.                INCLUDE 'string.asm'
  396.  
  397.                ; start of program
  398.  
  399.                mov     ax, 1000H             ;
  400.                mov     bx, 1000H             ;-- probably enough memory
  401.                mov     cx, 1000H             ;
  402.                call    MacAll                ;allocate macro memory
  403.                mov     ax, OFFSET file
  404.                call    MacCom                ;compile
  405.                call    MacRun                ;run
  406.                call    MacRel                ;release macro memory
  407.                mov     ax, 4C00H             ;terminate function
  408.                int     21H                   ;execute
  409.  
  410.        file    DB      'test.mac',0          ;name of macro file
  411.  
  412.        ; this adds the keywords TYPE and INPUT to the macro language
  413.  
  414.        MacUsr  LABEL   BYTE
  415.                DB      'TYPE',0, OFFSET TypeChar
  416.                DB      'INPUT',0, OFFSET InputChar
  417.                DB      0
  418.  
  419.  
  420.  
  421.        ; this is the TYPE service routine
  422.  
  423.        TypeChar PROC   FAR
  424.                call    MacLoa        ;load character
  425.                mov     dl, al
  426.                mov     ah, 2         ;DOS display function
  427.                int     21H           ;display character
  428.                ret
  429.                ENDP
  430.  
  431.        ; this is the INPUT service routine
  432.  
  433.        InputChar PROC  FAR
  434.                mov     ah, 8         ;DOS input function
  435.                int     21H           ;input a character
  436.                sub     ah, ah        ;zero high byte
  437.                call    MacSto        ;return it
  438.                ret
  439.                ENDP
  440.  
  441.      The following is a short macro that uses the keywords created above.
  442.      This macro should be copied to a file called TEST.MAC to be compiled
  443.      and run by the program above:
  444.  
  445.        // this macro inputs and echoes keystrokes until ESC is pressed;
  446.        // a CR is automatically followed by a LF; all control characters
  447.        // except CR and ESC are ignored
  448.  
  449.        begin JUMP                    // jump over skip
  450.  
  451.        : skip
  452.          DROP                        // drop the character
  453.  
  454.        : begin
  455.          INPUT                       // input a character
  456.          DUP 27 = exit ?JUMP         // jump to exit if ESC
  457.          DUP 13 = newline ?JUMP      // jump to newline if CR
  458.          DUP 32 < skip ?JUMP         // jump if skip if control character
  459.  
  460.          TYPE                        // type character
  461.          begin JUMP                  // loop back
  462.  
  463.        : newline
  464.          TYPE                        // type character (a CR)
  465.          10 TYPE                     // type a linefeed
  466.          begin JUMP                  // loop back
  467.  
  468.        : exit
  469.          DROP QUIT                   // drop ESC and quit
  470.